<?php
/**
 * @name PHPTree
 * @author crazymus < QQ:291445576 >
 * @des PHP生成树形结构,无限多级分类
 * @version 1.2.0
 * @Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
 * @updated 2015-08-26
 */
class Tree{
 
    protected static $config = array(
        /* 主键 */
        'primary_key' 	=> 'id',
        /* 父键 */
        'parent_key'  	=> 'pid',
        /* 展开属性 */
        'expanded_key'  => 'expanded',
        /* 叶子节点属性 */
        'leaf_key'      => 'leaf',
        /* 孩子节点属性 */
        'children_key'  => 'children',
        /* 是否展开子节点 */
        'expanded'    	=> false
    );
 
    /* 结果集 */
    protected static $result = array();
 
    /* 层次暂存 */
    protected static $level = array();
    /**
     * @name 生成树形结构
     * @param array 二维数组
     * @return mixed 多维数组
     */
    public static function makeTree($data,$options=array() ){
        if(empty($data)) return [];
        $dataset = self::buildData($data,$options);
        $r = self::makeTreeCore(0,$dataset,'normal');
        return $r;
    }
 
    /* 生成线性结构, 便于HTML输出, 参数同上 */
    public static function makeTreeForHtml($data,$options=array()){
        if(empty($data)) return [];
        $dataset = self::buildData($data,$options);
        $r = self::makeTreeCore(0,$dataset,'linear');
        return $r;
    }
 
    /* 格式化数据, 私有方法 */
    private static function buildData($data,$options){
        $config = array_merge(self::$config,$options);
        self::$config = $config;
        extract($config);
 
        $r = array();
        foreach($data as $item){
            $id = $item[$primary_key];
            $parent_id = $item[$parent_key];
            $r[$parent_id][$id] = $item;
        }
 
        return $r;
    }
 
    /* 生成树核心, 私有方法  */
    private static function makeTreeCore($index,$data,$type='linear')
    {
        extract(self::$config);
        foreach($data[$index] as $id=>$item)
        {
            if($type=='normal'){
                if(isset($data[$id]))
                {
                    $item[$expanded_key]= self::$config['expanded'];
                    $item[$children_key]= self::makeTreeCore($id,$data,$type);
                }
                else
                {
                    $item[$leaf_key]= true;
                }
                $r[] = $item;
            }else if($type=='linear'){
                $parent_id = $item[$parent_key];
                self::$level[$id] = $index==0?0:self::$level[$parent_id]+1;
                $item['level'] = self::$level[$id];
                self::$result[] = $item;
                if(isset($data[$id])){
                    self::makeTreeCore($id,$data,$type);
                }
 
                $r = self::$result;
            }
        }
        return $r;
    }
    
    //获取分类所有上级id
    public static function getParentsIds($data,$id,$andi=false){
        self::$result = [];
        if(empty($data) && !$andi) return [];
        $r = self::getIdsCore($data,$id);
        if($andi){
            $r = array_merge([$id],$r);
        }
        return $r;
    }
    
    //获取分类所有下级id
    public static function getChildsIds($data,$id,$andi=false){
        self::$result = [];
        if(empty($data) && !$andi) return [];
        $r = self::getIdsCore($data,$id,false);
        if($andi){
            $r = array_merge([$id],$r);
        }
        return $r;
    }
    
    //获取所有上级分类
    public static function getParents($data,$id,$andi=false){
        $ids = self::getParentsIds($data,$id,$andi);
        $r = [];
        foreach ($data as $key=>$val){
            if(in_array($val['id'], $ids)){
                $r[] = $val;
            }
        }
        return $r;
    }
    
    //获取所有下级分类
    public static function getChilds($data,$id,$andi=false){
        $ids = self::getChildsIds($data,$id,$andi);
        $r = [];
        foreach ($data as $key=>$val){
            if(in_array($val['id'], $ids)){
                $r[] = $val;
            }
        }
        return $r;
    }
    
    //获取分类所有上下级id
    private static function getIdsCore($data,$id,$isParent=true){
        foreach ($data as $key=>$val){
            if($isParent){
                if($val['pid'] > 0 && $val['id'] == $id){
                    self::$result[] = $val['pid'];
                    self::getIdsCore($data,$val['pid'],$isParent);
                }
            }else{
                if($val['pid'] == $id){
                    self::$result[] = $val['id'];
                    self::getIdsCore($data,$val['id'],$isParent);
                }
            }
        }
        $r = self::$result;
        return $r;
    }
    
    //获取分类树
    public static function getTree($data,$potion=array()){
        self::$result = [];
        $tree = self::makeTreeForHtml($data,$potion);
        
        foreach ($tree as $key=>$val){
            $flag = '';
            if(isset($val['level']) && $val['level'] > 0){
                for ($i=0;$i<$val['level'];$i++){
                    $flag .= $i==0?'┠─':'──';
                }
            }
            $tree[$key]['flag'] = $flag;
        }
        
        return $tree;
    }
}
 